package com.bigmodel.bistu;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import okhttp3.*;
import org.apache.logging.log4j.util.Strings;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;

import javax.net.ssl.*;
import java.io.FileOutputStream;
import java.math.BigInteger;
import java.util.*;

public class LNFSDataBuilder {
    private final static String LNFS_URL = "https://zhaoshengcx.bistu.edu.cn/f/ajax_lnfs?ts=${timestamp}";
    private final static String LNFS_PARAM_URL = "https://zhaoshengcx.bistu.edu.cn/f/ajax_lnfs_param?ts=${timestamp}";
    private final static String CSRF_TOKEN = "https://zhaoshengcx.bistu.edu.cn/f/ajax_get_csrfToken?ts=${timestamp}";
    private final static String OUT_PATH = "E:\\workspace\\LLM\\bigmodel\\word\\lnfs\\";
    Deque<String> tokenQueue = new ArrayDeque<>();

    /**
     * 分专业录取情况
     */
    JSONArray sszygradeList = new JSONArray();
    /**
     * 录取概况
     */
    JSONArray zsSsgradeList = new JSONArray();

    String sessionId = "";

    public void init() {

    }

    public void saveDocFile(String key) throws Exception {
        // 创建Word文档
        XWPFDocument document = new XWPFDocument();

        // 添加第一个二级标题
        XWPFParagraph zsSsgradeTitle = document.createParagraph();
        XWPFRun run1 = zsSsgradeTitle.createRun();
        run1.setText("录取概况");
        run1.setBold(true); // 设置为粗体

        // 创建录取概况表格的数据
        // 年份	省市	科类	类型	最高分	平均分	最低分	平均分排名	控制线
        List<List<String>> zsSsgradeData = new ArrayList<>();
        zsSsgradeData.add(Arrays.asList("年份", "省市", "科类", "类型", "最高分", "平均分", "最低分", "平均分排名", "控制线"));
        for (int i = 0; i < zsSsgradeList.size(); i++) {
            JSONObject zsSsgrade = zsSsgradeList.getJSONObject(i);
            List<String> zsSsgradeArr = Arrays.asList(
                    zsSsgrade.getStr("nf"),
                    zsSsgrade.getStr("ssmc"),
                    zsSsgrade.getStr("klmc"),
                    zsSsgrade.getStr("zslx"),
                    zsSsgrade.getStr("maxScore"),
                    zsSsgrade.getStr("avgScore"),
                    zsSsgrade.getStr("minScore"),
                    zsSsgrade.getStr("avgOrder"),
                    zsSsgrade.getStr("fsx")
            );
            zsSsgradeData.add(zsSsgradeArr);
        }

        // 创建并填充录取概况表格
        XWPFTable table1 = document.createTable(zsSsgradeData.size(), (zsSsgradeData.isEmpty() ? 0 : zsSsgradeData.get(0).size()));
        for (int row = 0; row < zsSsgradeData.size(); row++) {
            List<String> rowData = zsSsgradeData.get(row);
            for (int col = 0; col < rowData.size(); col++) {
                table1.getRow(row).getCell(col).setText(rowData.get(col));
                // 设置列宽为自动（Apache POI 5.x 及以上版本）
                if (table1.getCTTbl().getTblPr() == null) {
                    table1.getCTTbl().addNewTblPr();
                }
                table1.getCTTbl().getTblPr().addNewTblW().setW(BigInteger.valueOf(-1)); // 自动调整列宽
            }
        }

        // 添加第二个二级标题（可以添加一个空行来分隔）
        XWPFParagraph emptyLine = document.createParagraph(); // 创建一个空行
        XWPFParagraph sszygradeTitle = document.createParagraph();
        XWPFRun run2 = sszygradeTitle.createRun();
        run2.setText("分专业录取情况");
        run2.setBold(true); // 设置为粗体

        // 创建分专业录取情况表格的数据
        // 年份	省市	科类	类型	专业	最高分	平均分	最低分	平均分排名	控制线
        List<List<String>> sszygradeData = new ArrayList<>();
        sszygradeData.add(Arrays.asList("年份", "省市", "科类", "类型", "专业", "最高分", "平均分", "最低分", "平均分排名", "控制线"));
        for (int i = 0; i < sszygradeList.size(); i++) {
            JSONObject sszygrade = sszygradeList.getJSONObject(i);
            List<String> sszygradeArr = Arrays.asList(
                    sszygrade.getStr("nf"),
                    sszygrade.getStr("ssmc"),
                    sszygrade.getStr("klmc"),
                    sszygrade.getStr("zslx"),
                    sszygrade.getStr("zymc"),
                    sszygrade.getStr("maxScore"),
                    sszygrade.getStr("avgScore"),
                    sszygrade.getStr("minScore"),
                    sszygrade.getStr("avgOrder"),
                    sszygrade.getStr("fsx")
            );
            sszygradeData.add(sszygradeArr);
        }

        // 创建并填充分专业录取情况表格
        XWPFTable table2 = document.createTable(sszygradeData.size(), (sszygradeData.isEmpty() ? 0 : sszygradeData.get(0).size()));
        for (int row = 0; row < sszygradeData.size(); row++) {
            List<String> rowData = sszygradeData.get(row);
            for (int col = 0; col < rowData.size(); col++) {
                table2.getRow(row).getCell(col).setText(rowData.get(col));
                // 设置列宽为自动（Apache POI 5.x 及以上版本）
                if (table2.getCTTbl().getTblPr() == null) {
                    table2.getCTTbl().addNewTblPr();
                }
                table2.getCTTbl().getTblPr().addNewTblW().setW(BigInteger.valueOf(-1)); // 自动调整列宽
            }
        }

        // 写入到文件
        try (FileOutputStream out = new FileOutputStream(OUT_PATH + key + "-历年分数.docx")) {
            document.write(out);
        }

        // 清理数据
        sszygradeList.clear();
        zsSsgradeList.clear();
    }

    public void getData(Map<String, String> param) throws Exception {
        String timestamp = System.currentTimeMillis() + "";
        String url = LNFS_URL.replace("${timestamp}", timestamp);
        RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
                .addFormDataPart("ssmc", param.get("ssmc"))
                .addFormDataPart("zsnf", param.get("zsnf"))
                .addFormDataPart("klmc", param.get("klmc"))
                .addFormDataPart("zslx", param.get("zslx"))
                .build();
        String result = httpPost(url, body, timestamp);
        System.out.println(result);
        Map<String, Object> map = JSONUtil.toBean(result, Map.class);
        JSONObject data = (JSONObject)map.get("data");
        JSONArray sszygradeList = data.getJSONArray("sszygradeList");
        JSONArray zsSsgradeList = data.getJSONArray("zsSsgradeList");
        this.sszygradeList.addAll(sszygradeList);
        this.zsSsgradeList.addAll(zsSsgradeList);
        System.out.println(this.sszygradeList);
        System.out.println(this.zsSsgradeList);
    }

    public JSONObject getParam() throws Exception {
        String timestamp = System.currentTimeMillis() + "";
        String url = LNFS_PARAM_URL.replace("${timestamp}", timestamp);
        RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
                .addFormDataPart("n","3")
                .build();
        String result = httpPost(url, body, timestamp);
        Map<String, Object> map = JSONUtil.toBean(result, Map.class);
        JSONObject data = (JSONObject)map.get("data");
        JSONObject param = data.getJSONObject("ssmc_nf_klmc_sex_campus_zslx_Map");
        return param;
    }

    public void getTokenByHttp() throws Exception {
        tokenQueue.clear();
        String timestamp = System.currentTimeMillis() + "";
        String url = CSRF_TOKEN.replace("${timestamp}", timestamp);

        RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
                .addFormDataPart("n","3")
                .build();
        String result = httpPost(url, body, timestamp);
        Map<String, Object> map = JSONUtil.toBean(result, Map.class);
        String[] tokens = map.get("data").toString().split(",");
        for (int i = 0; i < tokens.length; i++) {
            tokenQueue.offer(tokens[i]);
        }
        sessionId = map.get("jessionid").toString();
    }

    public String httpPost(String url, RequestBody body, String timestamp) throws Exception {
        // 创建一个信任所有证书的TrustManager
        final TrustManager[] trustAllCerts = new TrustManager[] {
                new X509TrustManager() {
                    @Override
                    public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {
                    }

                    @Override
                    public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) {
                    }

                    @Override
                    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                        return new java.security.cert.X509Certificate[]{};
                    }
                }
        };

        // 初始化SSLContext
        final SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());

        // 创建一个SSLSocketFactory
        final SSLSocketFactory sslSocketFactory = sc.getSocketFactory();

        OkHttpClient client = new OkHttpClient().newBuilder()
                .sslSocketFactory(sslSocketFactory, (X509TrustManager)trustAllCerts[0])
                .hostnameVerifier(new HostnameVerifier() {
                    @Override
                    public boolean verify(String hostname, SSLSession session) {
                        return true; // 不验证主机名
                    }
                })
                .build();

        String csrfToken = tokenQueue.peek();
        if (csrfToken == null) {
            csrfToken = "";
        }

        String sessionId = "cb31602d0f8d4d6a923daa8f0fb8d99c";
        if (!Strings.isEmpty(this.sessionId)) {
            sessionId = this.sessionId;
        }

        Headers headers = new Headers.Builder()
                .add("Referer", "https://zhaoshengcx.bistu.edu.cn/static/front/bistu/basic/html_web/lnfs.html")
                .add("Origin", "https://zhaoshengcx.bistu.edu.cn")
                .add("Sec-Fetch-Dest", "empty")
                .add("Sec-Fetch-Mode", "cors")
                .add("X-Requested-Time", timestamp)
                .add("Csrf-Token", csrfToken)
                .add("Cookie", "zhaosheng.bistu.session.id=" + sessionId)
                .build();
        Request request = new Request.Builder()
                .url(url)
                .method("POST", body)
                .headers(headers)
                .build();
        Response response = client.newCall(request).execute();
        return response.body().string();
    }
}
